home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / gc / GCconstrained_malloc.c < prev    next >
C/C++ Source or Header  |  1991-12-13  |  4KB  |  141 lines

  1.  
  2. /*
  3.  * Allocate a pointerful block of at least *size bytes, starting within
  4.  * maxDist bytes of address.  Returns NIL if unsuccessful.
  5.  * May take a long time, especially if unsuccessful.
  6.  * If successful, the actual size is returned in *size.
  7.  * The address argument should be an address in or below the heap.
  8.  */
  9.  
  10. # include <xr/GC.h>
  11. # include <xr/GCPrivate.h>
  12.  
  13. XR_Pointer XR_ConstrainedMalloc(size, address, maxDist)
  14. unsigned long * size;
  15. XR_Pointer address;
  16. unsigned long maxDist;
  17. {
  18.     register unsigned long lw;
  19.     struct obj * result;
  20.     register struct obj * op;
  21.     register struct obj * last;
  22.     register struct obj * lb;
  23.     register struct obj * ub;
  24.     struct obj * garbage = 0;  /* List (linked through 0th comp) of     */
  25.                         /* unusable objects we already allocated */
  26.     int initial_gc_no = GC_gc_no;
  27.     
  28.     if (address > (XR_Pointer)GC_heaplim) {
  29.         return(0);
  30.     }     
  31.     if (((unsigned long)address) < maxDist) {
  32.         lb = 0;
  33.     } else {
  34.         lb = (struct obj *)(((unsigned long)address) - maxDist);
  35.     }
  36.     ub = (struct obj *)(((unsigned long)address) + maxDist);
  37. #   define in_range(p) ((p) <= ub && (p) >= lb)
  38.     XR_MonitorEntry(&GC_allocate_ml);
  39.     for(;;) {
  40.       /* First try small object free lists: */
  41.     for (lw = BYTES_TO_WORDS(*size + (sizeof (word)) -1);
  42.          lw <= MAXOBJSZ; lw++) {
  43. #           ifdef MERGE_SIZES
  44.           lw = GC_size_map[lw];
  45. #           endif
  46.         if (op = objfreelist[lw]) {
  47.           if (in_range(op)) {
  48.             objfreelist[lw] = get_obj_link(op);
  49.             op->obj_component[0] = 0;
  50.             result = op;
  51.             *size = WORDS_TO_BYTES(lw);
  52.             goto done;
  53.           } else {
  54.             last = op;
  55.             while (op = get_obj_link(last)) {
  56.               if (in_range(op)) {
  57.                 set_obj_link(last, get_obj_link(op));
  58.                 op -> obj_component[0] = 0;
  59.                 result = op;
  60.                 *size = WORDS_TO_BYTES(lw);
  61.                 goto done;
  62.               } else {
  63.                 last = op;
  64.               }
  65.             }
  66.           }
  67.         }
  68.     }
  69.       /* Repeatedly try to allocate heap blocks until we get an appropriate */
  70.       /* one, or we run out.  Explicitly discard unused blocks once we're   */
  71.       /* done.                                   */
  72.       {
  73.           extern struct hblk * GC_savhbp;  /* Start point for heap block */
  74.                             /* allocator.         */
  75.           struct hblk * hbp;
  76.           struct hblk * prevhbp;
  77.          
  78.           lw = (*size + HDR_BYTES + HBLKSIZE-1) & ~HBLKMASK; 
  79.           lw -= HDR_BYTES;
  80.           lw = BYTES_TO_WORDS(lw);
  81.           /* Try to set GC_savhbp to one before the first block that's */
  82.           /* in range.                                                 */
  83.             prevhbp = 0;
  84.             hbp = GC_hblkfreelist;
  85.             while(hbp != 0 && !in_range((struct obj *)hbp)) {
  86.                 prevhbp = hbp;
  87.                 hbp = hb_next(hbp);
  88.             }
  89.             GC_savhbp = prevhbp;
  90.             while (((struct obj *)GC_heaplim) <= ub || GC_sufficient_hb(lw)) {
  91.               hbp = GC_allochblk(lw);
  92.               if (hbp == 0) {
  93.                   goto done;
  94.               }
  95.               GC_add_hblklist(hbp);
  96.               op = (struct obj *) (hbp -> hb_body);
  97.               if (in_range(op)) {
  98.                   result = op;
  99.               *size = WORDS_TO_BYTES(lw);
  100.               goto done;
  101.               } else {
  102.                   op -> obj_component[0] = (word)garbage;
  103.                   garbage = op;
  104.               }
  105.             }
  106.       }
  107.       if (GC_gc_no == initial_gc_no) {
  108.         GC_demand_full_and_wait();
  109.         XR_MonitorExit(&GC_allocate_ml);
  110.         {
  111.           register struct hblk ** rlp;
  112.           
  113.           for( rlp = reclaim_list; rlp < &reclaim_list[MAXOBJSZ+1]; rlp++ ) {
  114.         while (*rlp != (struct hblk *)0) {
  115.             GC_reclaim_composite(rlp);
  116.         }
  117.       }
  118.       for( rlp = areclaim_list; rlp < &areclaim_list[MAXOBJSZ+1]; rlp++ ) {
  119.         while (*rlp != (struct hblk *)0) {
  120.             GC_reclaim_atomic(rlp);
  121.         }
  122.       }
  123.         }
  124.         XR_MonitorEntry(&GC_allocate_ml);
  125.       } else {
  126.         break;
  127.       }
  128.     }
  129.     result = 0;
  130.      
  131.    done:
  132.     XR_MonitorExit(&GC_allocate_ml);
  133.     /* Delete unused heap blocks */
  134.         while (garbage != (struct obj *)0) {
  135.             op = garbage;
  136.             garbage = (struct obj *)(garbage -> obj_component[0]);
  137.             GC_free(op);
  138.         }
  139.     return((XR_Pointer)result);
  140. }
  141.